using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using UnityEngine;

public class commonDLL {
#if UNITY_IPHONE
	const string dll_tag = "__Internal";
#else
    const string dll_tag = "common";
#endif

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate void d_connectStateChangeEvent(IntPtr sock,int state);    
    static void S_StateEvent(IntPtr sock, int state) {
        if (o_clientSocket == IntPtr.Zero) {
            o_clientSocket = sock;
        }
        if (_connectStateChangeEvent == null) {
            Debug.LogErrorFormat("链接状态改变.消息..___" + state);
            return; 
        }
        try {
            _connectStateChangeEvent(state);
        } catch {
            Debug.LogErrorFormat("错误..___" + state);
        }
    }
    static IntPtr o_clientSocket;
    static Action<int> _connectStateChangeEvent;

    [DllImport(dll_tag, CallingConvention = CallingConvention.Cdecl)]
    static extern IntPtr C_ClientSocket_Connect(string ip, ushort port, d_connectStateChangeEvent d_StateEvent);
    [DllImport(dll_tag, CallingConvention = CallingConvention.Cdecl)]
    static extern void C_ClientSocket_Send(IntPtr sock);
    [DllImport(dll_tag, CallingConvention = CallingConvention.Cdecl)]
    static extern void C_ClientSocket_SendChars(IntPtr sock, byte[] msg, int msgLen);
    [DllImport(dll_tag, CallingConvention = CallingConvention.Cdecl)]
    static extern IntPtr C_ClientSocket_getNextMsg(IntPtr sock);    
    [DllImport(dll_tag, CallingConvention = CallingConvention.Cdecl)]
    static extern void C_ClientSocket_Close(IntPtr sock);   
    [DllImport(dll_tag, CallingConvention = CallingConvention.Cdecl)]
    static extern int Byte_GetLength(IntPtr data);
    [DllImport(dll_tag, CallingConvention = CallingConvention.Cdecl)]
    static extern IntPtr Byte_GetByte(IntPtr data);  
    public class C_ClientSocket : MonoBehaviour  {   
        static C_ClientSocket instance;   
        public static void S_Connect(string ip, ushort port, Action<int> d_connectStateChangeEvent,Action<byte[]> d_msgEvent) {
            _connectStateChangeEvent = d_connectStateChangeEvent;
            d_msgEvent0 = d_msgEvent;
            Debug.LogFormat("链接........{0}....{1}", ip, port);
            o_clientSocket = C_ClientSocket_Connect(ip, port, S_StateEvent); 
            if (instance == null) {          
                instance = new GameObject("C_ClientSocket.Mono").AddComponent<C_ClientSocket>();
                GameObject.DontDestroyOnLoad(instance.gameObject);   
            }
        }

        static Action<byte[]> d_msgEvent0;     
        public void Update() {
      
            IntPtr msg = C_ClientSocket_getNextMsg(o_clientSocket);
            if(msg == IntPtr.Zero) {
                return;
            }
            int len = Byte_GetLength(msg);
            //Debug.LogFormat("读取长度.......{0}.", len);
            if (len > 0) {   
                if (d_msgEvent0 == null) { return; }
                byte[] bytes = new byte[len];
                IntPtr byt = Byte_GetByte(msg);      
                Marshal.Copy(byt, bytes, 0, len);
                try {
                    d_msgEvent0(bytes);
                } catch {
                    Debug.LogErrorFormat("错误..___");
                }
            }
            //S_Send("牛逼消息string msg");
        }
        public static void S_Send(string msg) {
            byte[] bytes = Encoding.UTF8.GetBytes(msg);
            //Debug.LogFormat("S_Send..___.....{0}", bytes.Length);
            C_ClientSocket_SendChars(o_clientSocket, bytes, bytes.Length);
        }
        public void S_Send(byte[] bytes) {

        }
        public struct tagPOINT_2D {
            public double m_dbX;
            public double m_dbY;
        } 
        public struct tagGISPOINTS {
            public int m_nPointCount;
            public tagPOINT_2D[] m_arrPoints;
        }
        private void ReadWayPoint(byte[] byteArray) {
            tagGISPOINTS[] tag = new tagGISPOINTS[1];

            GCHandle gch = GCHandle.Alloc(tag, GCHandleType.Pinned);
            IntPtr ptr = gch.AddrOfPinnedObject();
            Marshal.Copy(byteArray, 0, ptr, byteArray.Length);
            gch.Free();

            tagGISPOINTS gisPt = tag[0];
            int size = tag[0].m_nPointCount;

            ///////////////////////////////////////////////////////////////////
            int iii = Marshal.SizeOf(typeof(tagPOINT_2D)) * size;
            byte[] byteNew = new byte[iii];
            Array.Copy(byteArray, 8, byteNew, 0, byteNew.Length);

            tagPOINT_2D[] pts = new tagPOINT_2D[size + 1];
            gch = GCHandle.Alloc(pts, GCHandleType.Pinned);
            ptr = gch.AddrOfPinnedObject();
            Marshal.Copy(byteNew, 0, ptr, byteNew.Length);
            gch.Free();
        }

        void OnApplicationQuit() {
            S_ApplicationQuit();
        }
        void OnDestroy() {
            S_ApplicationQuit();
        }

        void S_ApplicationQuit() {
#if UNITY_EDITOR
            //C_Log.LogErrorFormat("客户端退出...----关闭通信对象---");
            C_ClientSocket_Close(o_clientSocket);
            GC.Collect();
#endif
        }
    }
}

public class C_Byte {
    public byte[] o_byte;
    public uint o_len;
}
